#include <userver/ydb/exceptions.hpp>

#include <ydb-cpp-sdk/client/types/status/status.h>

#include <fmt/format.h>

USERVER_NAMESPACE_BEGIN

namespace ydb {

YdbResponseError::YdbResponseError(std::string_view operation_name, NYdb::TStatus&& status)
    : BaseError(fmt::format("YDB {} failed: {}", operation_name, status.GetIssues().ToOneLineString())),
      status_(std::move(status))
{}

const NYdb::TStatus& YdbResponseError::GetStatus() const noexcept { return status_; }

UndefinedDatabaseError::UndefinedDatabaseError(std::string error)
    : BaseError(std::move(error))
{}

EmptyResponseError::EmptyResponseError(std::string_view expected)
    : BaseError(fmt::format("Unexpected YDB empty response: no response and no errors for '{}'", expected))
{}

ParseError::ParseError(std::string error)
    : BaseError(std::move(error))
{}

ColumnParseError::ColumnParseError(std::string_view column_name, std::string_view message)
    : ParseError(fmt::format("Unexpected contents of column '{}' in YDB response: {}", column_name, message))
{}

TypeMismatchError::TypeMismatchError(std::string_view name, std::string_view expected, std::string_view actual)
    : BaseError(fmt::format("Field '{}' is of a wrong type. Expected: {}, actual: {}", name, expected, actual))
{}

DeadlineExceededError::DeadlineExceededError(std::string msg)
    : BaseError(std::move(msg))
{}

OperationCancelledError::OperationCancelledError()
    : BaseError("Cannot wait for future: operation cancelled")
{}

InvalidTransactionError::InvalidTransactionError()
    : BaseError("Transaction is used after it is already finished")
{}

ResponseTruncatedError::ResponseTruncatedError()
    : BaseError("Response is truncated")
{}

TransactionForceRollback::TransactionForceRollback()
    : BaseError("Force rollback due to Testpoint response")
{}

IgnoreResultsError::IgnoreResultsError(std::string err)
    : BaseError(err)
{}

}  // namespace ydb

USERVER_NAMESPACE_END
